<?php
/**
 * Smart Library - Smart Framework
 * http://smart-framework.highet.eu
 *
 * @category   SmartL
 * @package    SmartL_Zend
 * @subpackage Validate
 * @copyright  Copyright (c) 2005-2008 Smart Framework team - Stepan Sindelar, Vojtech Vit
 * @license    http://www.opensource.org/licenses/bsd-license.php	New BSD License
 */

/**
 * @see Zend_Validate_Abstract
 */
require_once 'Zend/Validate/Abstract.php';
/**
 * @see Zend_Loader_PluginLoader
 */
require_once 'Zend/Loader/PluginLoader.php';

/**
 * Validator for common scenario like validating if username is unique.
 *
 * @package SmartL_Zend
 * @subpackage Validate
 */
class SmartL_Zend_Validate_Unique extends Zend_Validate_Abstract {
	/**
	 * Constaint for error message.
	 *
	 */
	const NOT_UNIQUE = 'notUnique';
	/**
	 * Error messages array.
	 *
	 * @var array
	 */	
	protected $_messageTemplates = array (self::NOT_UNIQUE => 'Element has not unique value %s' );
	/**
	 * Values to compare with this value.
	 *
	 * @var array
	 */
	private $_compare = array ();
	/**
	 *
	 *
	 * @var array[numeric]=>SmartL_Zend_Validate_Unique_DataAdapter_Interface
	 */
	private $_adapters = array ();
	/**
	 * Data adapters loader.
	 *
	 * @var Zend_Plugin_PluginLoader
	 */
	private $_loader = null;
	
	public function __construct($values = array(), $adapters = array()) {
		$this->setCompareValues ( $values );
		foreach ( $adapters as $adapter ) {
			$this->addDataStore ( $adapter ['adapterName'], $adapter );
		}
	}
	
	public function getLoader() {
		if (! isset ( $this->_loader )) {
			$this->_loader = new Zend_Loader_PluginLoader ( );
			$this->_loader->addPrefixPath ( 'SmartL_Zend_Validate_Unique_DataAdapter', 'SmartL' . DIRECTORY_SEPARATOR . 'Zend' . DIRECTORY_SEPARATOR . 'Validate' . DIRECTORY_SEPARATOR . 'Unique' . DIRECTORY_SEPARATOR . 'DataAdapter' );
		}
		return $this->_loader;
	}
	
	public function setLoader(Zend_Plugin_PluginLoader $loader) {
		$this->_loader = $loader;
	}
	
	public function addDataStore($adapter, array $config = array()) {
		if (is_object ( $adapter )) {
			if (! $adapter instanceof SmartL_Zend_Validate_Unique_DataAdapter_Interface) {
				require_once 'SmartL/Zend/Validate/Unique/Exception.php';
				throw new SmartL_Zend_Validate_Unique_Exception ( "Adapter for data store for unique validator must 
    				be instance of SmartL_Zend_Validate_Unique_DataAdapter_Interface" );
			}
			$this->_adapters [] = $adapter;
		} else {
			$class = $this->getLoader ()->load ( $adapter );
			$this->_adapters [] = new $class ( $config );
		}
	}
	/**
	 * These values will be compared with value of validating element.
	 *
	 * @param array $values
	 */
	public function setCompareValues(array $values) {
		$this->_compare = $values;
	}
	/**
	 * Process validation and return results.
	 * It is implemetation of method from Zend_Validate_Abstract.
	 *
	 * @param string $value Value of checked field.
	 * @param array $context Values of other fields in form.
	 * @return boolean
	 */
	public function isValid($value, $context = null) {
		//set value
		$value = ( string ) $value;
		$this->_setValue ( $value );
		//make result
		$result = (array_search ( $value, $this->_compare ) === false);
		foreach ( $this->_adapters as $adapter ) {
			$result = ($result and $adapter->isUnique ( $value ));
			if (! $result)
				break;
		}
		//any error
		if (! $result) {
			$this->_error ( self::NOT_UNIQUE );
		}
		//return result
		return $result;
	}
}